/*
 * Copyright (c) 2025 Industrial Software Feature Database
 */
package com.comac.ins.isfd.rpc.isfd.oauth;

import cn.hutool.json.JSONObject;
import com.comac.ins.common.core.exception.base.BaseException;
import com.comac.ins.common.redis.utils.RedisUtils;
import com.comac.ins.isfd.constant.RedisConstants;
import com.comac.ins.isfd.rpc.isfd.bo.IsfdLoginBo;
import com.comac.ins.isfd.rpc.isfd.config.IsfdRequestConfig;
import com.comac.ins.isfd.rpc.isfd.constants.IsfdConstants;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.time.Duration;

@Component
public class IsfdOauthTokenUtils {

    @Autowired
    private RestTemplate tokenRestTemplate;

    /**
     * 先从缓存获取，获取不到再去第三方获取，获取到后放入缓存，
     * 缓存时间要小于过期时间
     */
    public String getCurrentToken(IsfdRequestConfig isfdRequestConfig, Boolean needFromCache) {
        String protocol = isfdRequestConfig.getProtocol();
        String host = isfdRequestConfig.getHost();
        Integer port = isfdRequestConfig.getPort();
        String username = isfdRequestConfig.getUsername();
        String password = isfdRequestConfig.getPassword();
        String tenantId = isfdRequestConfig.getTenantId();
        String grantType = isfdRequestConfig.getGrantType();
        Boolean rememberMe = isfdRequestConfig.getRememberMe();
        String clientId = isfdRequestConfig.getClientId();

        // 1.获取缓存
        String oauthKey = RedisConstants.ISFD_ACCESS_TOKEN_KEY + username;
        String accessToken = null;
        if (needFromCache) {
            accessToken = RedisUtils.getCacheObject(oauthKey);
            if (StringUtils.isNotBlank(accessToken)) {
                return accessToken;
            }
        }

        // 2.缓存获取不了，去第三方认证
        // 请求路径
        String url = String.format("%s://%s:%d%s", protocol, host, port, IsfdConstants.AUTHENTICATION_URI);
        // 创建请求头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);

        // 创建请求体
        IsfdLoginBo isfdLoginBo = new IsfdLoginBo();
        isfdLoginBo.setTenantId(tenantId);
        isfdLoginBo.setUsername(username);
        isfdLoginBo.setPassword(password);
        isfdLoginBo.setGrantType(grantType);
        isfdLoginBo.setClientId(clientId);
        isfdLoginBo.setRememberMe(rememberMe);

        HttpEntity<Object> entity = new HttpEntity<>(isfdLoginBo, headers);
        ResponseEntity<JSONObject> response = tokenRestTemplate.exchange(url, HttpMethod.POST, entity, JSONObject.class);
        // 从响应中提取 token
        if (!response.getStatusCode().is2xxSuccessful()) {
            throw new BaseException("Failed to obtain token: " + response.getStatusCode());
        }
        JSONObject body = response.getBody();
        if (body == null) {
            throw new BaseException("获取要素数据库token失败，返回体body为空。");
        }
        Integer code = body.getInt(IsfdConstants.CODE);
        if (code == null || code != HttpStatus.OK.value()) {
            throw new BaseException("获取要素数据库token失败，返回体body中的code为：" + code + "，msg为：" + body.getStr(IsfdConstants.MSG));
        }

        JSONObject data = body.getJSONObject(IsfdConstants.DATA);
        accessToken = data.getStr(IsfdConstants.ACCESS_TOKEN);
        if (StringUtils.isBlank(accessToken)) {
            throw new BaseException("获取要素数据库token失败，accessToken为空");
        }
        // 3.把accessToken放入redis
        Integer targetExpireTime = data.getInt(IsfdConstants.EXPIRE_IN);
        Integer expireTime = RedisConstants.ISFD_ACCESS_TOKEN_KEY_EXPIRE_FOR_SEC;
        if (targetExpireTime != null && targetExpireTime <= expireTime) {
            expireTime = targetExpireTime;
        }
        RedisUtils.setCacheObject(oauthKey, accessToken, Duration.ofSeconds(expireTime));
        return accessToken;
    }
}
